/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.stobml.tests;

import com.sun.xml.internal.messaging.saaj.util.ByteInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import org.stobml.STOBNode;
import org.stobml.STOBParser;

/**
 *
 * @author ivan
 */
public class Tests {

    private static class ExpectedItem{
        public enum EType{
            STRING,
            CHILD_BEGIN,
            CHILD_END
        }
        public EType type;
        public String str;

        public ExpectedItem(EType type, String str){
            this.type = type;
            this.str = str;
        }
    };
    
    private static void testParser(){
        final List<ExpectedItem> expected = new ArrayList<>();

        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, "ttt"));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, "test string"));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, "anot/her string"));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, "unqu/otedString"));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, "string with empty children list"));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_BEGIN, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_END, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, "unquoted_string_with_empty_children_list"));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_BEGIN, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_END, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, "string_interrupted_by_comment"));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, "string_broken_by_comment"));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_BEGIN, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_END, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, ""));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_BEGIN, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_END, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, ""));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_BEGIN, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, ""));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_BEGIN, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_END, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, ""));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_BEGIN, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_END, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_END, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, ""));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_BEGIN, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, "child string"));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, "aaa"));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_BEGIN, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_END, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, "bbb"));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, "ccc"));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_BEGIN, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, "ddd"));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_END, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, ""));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_BEGIN, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_END, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.CHILD_END, null));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, "Tab\t Backslash\\ Slash/ Doubleslash// Newline\n Carriagereturn\r Doublequotes\" {}{}{}{}"));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, "quoted string with trailing slash /"));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, "fff ggg"));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, "tralala tro lo lo\ntre lele"));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, "-1213.33"));
        expected.add (new ExpectedItem (ExpectedItem.EType.STRING, "UnquotedStringAtTheVeryEndOfTheFile"));

        try{
            STOBParser.Parse(
                    new FileInputStream("test.stob"),
                    new STOBParser.Listener() {
                        @Override
                        public void onStringParsed(String str) {
                            assert(expected.get(0).type == ExpectedItem.EType.STRING);
                            assert(expected.get(0).str.equals(str));
                            expected.remove(0);
                        }

                        @Override
                        public void onChildrenParseStarted() {
                            assert(expected.get(0).type == ExpectedItem.EType.CHILD_BEGIN);
                            expected.remove(0);
                        }

                        @Override
                        public void onChildrenParseFinished() {
                            assert(expected.get(0).type == ExpectedItem.EType.CHILD_END);
                            expected.remove(0);
                        }
                    }
                );
        }catch(IOException e){
            e.printStackTrace();
            assert(false);
        }catch(STOBParser.FormatException e){
            e.printStackTrace();
            assert(false);
        }
    }
    
    private static void testDom(){
        List<STOBNode> expectedDom = new ArrayList<>();
        
        expectedDom.add(new STOBNode("ttt"));
        expectedDom.add(new STOBNode("test string"));
        expectedDom.add(new STOBNode("anot/her string"));
        expectedDom.add(new STOBNode("unqu/otedString"));
        expectedDom.add(new STOBNode("string with empty children list"));
        expectedDom.add(new STOBNode("unquoted_string_with_empty_children_list"));
        expectedDom.add(new STOBNode("string_interrupted_by_comment"));
        expectedDom.add(new STOBNode("string_broken_by_comment"));
        expectedDom.add(new STOBNode());
        {
            STOBNode n = new STOBNode();
            n.add(new STOBNode());
            n.add(new STOBNode());
            expectedDom.add(n);
        }
        {
            STOBNode n = new STOBNode();
            n.add(new STOBNode("child string"));
            n.add(new STOBNode("aaa"));
            n.add(new STOBNode("bbb"));
            {
                STOBNode n1 = new STOBNode("ccc");
                n1.add(new STOBNode("ddd"));
                n.add(n1);
            }
            n.add(new STOBNode());
            
            expectedDom.add(n);
        }
        expectedDom.add(new STOBNode("Tab\t Backslash\\ Slash/ Doubleslash// Newline\n Carriagereturn\r Doublequotes\" {}{}{}{}"));
        expectedDom.add(new STOBNode("quoted string with trailing slash /"));
        expectedDom.add(new STOBNode("fff ggg"));
        expectedDom.add(new STOBNode("tralala tro lo lo\ntre lele"));
        expectedDom.add(new STOBNode("-1213.33"));
        expectedDom.add(new STOBNode("UnquotedStringAtTheVeryEndOfTheFile"));
        
        try{
            List<STOBNode> dom = STOBNode.load(new FileInputStream("test.stob"));
            assert(STOBNode.compareChains(dom, expectedDom));
        }catch(IOException e){
            assert(false);
        }catch(STOBParser.FormatException e){
            assert(false);
        }
    }
    
    private static void testWritingDom(){
        try{
            for(int i = 0; i != 2; ++i){
                List<STOBNode> dom = STOBNode.load(new FileInputStream("test.stob"));

                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                STOBNode.write(baos, dom, i == 0);

                byte[] array = baos.toByteArray();

                String text = new String(array, StandardCharsets.UTF_8);
    //            System.out.println(text);

                ByteInputStream bis = new ByteInputStream(array, array.length);

                List<STOBNode> dom1 = STOBNode.load(bis);

                assert(STOBNode.compareChains(dom, dom1));
            }
        }catch(IOException e){
            assert(false);
        }catch(STOBParser.FormatException e){
            assert(false);
        }
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        testParser();
        testDom();
        testWritingDom();
        
        System.out.println("TEST FINISHED!!!");
    }
    
}
